package com.k8.common.aop.internal.interceptor;

import com.k8.common.aop.internal.advice.AdviceOrderEnum;
import com.k8.common.aop.internal.advice.AroundAdvice;
import com.k8.common.aop.internal.invocation.MethodInvocation;
import com.k8.common.aop.internal.invocation.ReflectiveMethodInvocation;
import com.k8.common.aop.internal.joinpoint.JoinPoint;
import com.k8.common.aop.internal.joinpoint.ProceedingJoinPoint;
import com.k8.common.util.AopUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class AroundMethodInterceptor extends ProxyMethodExecutor implements AroundAdvice {
    public AroundMethodInterceptor(Object target, Method targetMethod) {
        super(target, targetMethod);
    }

    @Override
    public int getAdviceOrder() {
        return AroundAdvice.super.getAdviceOrder();
    }

    @Override
    boolean judgeJointPointArgument(Parameter parameter) {
        return parameter.getType().isAssignableFrom(ProceedingJoinPoint.class);
    }

    @Override
    public void preInvokeProceed() {
        Object[] arguments=new Object[super.getAdviceMethodParas().length];
        if (joinPointIndex>=0){
            MethodInvocation methodInvocation = ExposeInvocationInterceptor.currentMethodInvocation();
            if (methodInvocation instanceof ReflectiveMethodInvocation pmi){
                JoinPoint joinPoint = pmi.getJoinPoint();
                ProceedingJoinPoint proceedingJoinPoint=new ProceedingJoinPoint(joinPoint,pmi);
                arguments[joinPointIndex]=proceedingJoinPoint;
                super.setCacheParas(arguments);
            }
        }
    }

    @Override
    boolean judgeArgument(Parameter parameter, Method targetMethod) {
        return AopUtil.judgeJoinAdviceArgs(parameter, AdviceOrderEnum.Around,targetMethod);
    }

    @Override
    Object invoke0(MethodInvocation invocation) throws Throwable {
        return super.invokeAround();
    }
}
